using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.SignalR;
using System.Security.Claims;
using CollabApp.API.Common;
using CollabApp.API.DTOs.Room;
using CollabApp.API.DTOs.Game;
using CollabApp.API.Hubs;
using CollabApp.Domain.Services.Room;
using CollabApp.Domain.Entities.Room;
using CollabApp.Application.Interfaces;

namespace CollabApp.API.Controllers;

/// <summary>
/// 房间管理控制器
/// 提供游戏房间的创建、加入、管理等功能
/// </summary>
[ApiController]
[Route("api/[controller]")]
[Authorize]
public class RoomController : ControllerBase
{
    private readonly IRoomService _roomService;
    private readonly ILineDrawingGameService _gameService;
    private readonly IHubContext<GameHub> _hubContext;
    private readonly ILogger<RoomController> _logger;

    public RoomController(
        IRoomService roomService, 
        ILineDrawingGameService gameService,
        IHubContext<GameHub> hubContext, 
        ILogger<RoomController> logger)
    {
        _roomService = roomService ?? throw new ArgumentNullException(nameof(roomService));
        _gameService = gameService ?? throw new ArgumentNullException(nameof(gameService));
        _hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    /// <summary>
    /// 创建游戏房间
    /// POST /api/room/create
    /// </summary>
    [HttpPost("create")]
    public async Task<ActionResult<ApiResponse<object>>> CreateRoomAsync([FromBody] CreateRoomRequest request)
    {
        try
        {
            var userId = GetCurrentUserId();
            if (userId == Guid.Empty)
            {
                return Unauthorized(ApiResponse<object>.CreateFailure("用户未认证"));
            }

            _logger.LogInformation("用户 {UserId} 创建房间: {RoomName}", userId, request.RoomName);

            var room = await _roomService.CreateRoomAsync(
                name: request.RoomName,
                ownerId: userId,
                maxPlayers: request.MaxPlayers,
                password: request.Password,
                isPrivate: request.IsPrivate
            );

            return Ok(ApiResponse<object>.CreateSuccess(new
            {
                RoomId = room.Id,
                RoomName = room.Name,
                HostId = room.OwnerId,
                MaxPlayers = room.MaxPlayers,
                IsPrivate = room.IsPrivate,
                Status = room.Status.ToString(),
                CreatedAt = room.CreatedAt
            }, "房间创建成功"));
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "创建房间时发生错误");
            return StatusCode(500, ApiResponse<object>.CreateFailure("创建房间失败"));
        }
    }

    /// <summary>
    /// 获取房间列表
    /// GET /api/room/list
    /// </summary>
    [HttpGet("list")]
    public async Task<ActionResult<ApiResponse<object>>> GetRoomListAsync(
        [FromQuery] int page = 1, 
        [FromQuery] int pageSize = 20,
        [FromQuery] string? gameMode = null,
        [FromQuery] bool? hasPassword = null,
        [FromQuery] string? status = null)
    {
        try
        {
            _logger.LogDebug("获取房间列表: Page={Page}, PageSize={PageSize}, GameMode={GameMode}", 
                page, pageSize, gameMode);

            var roomListResult = await _roomService.GetRoomListAsync(
                pageNumber: page,
                pageSize: pageSize,
                includePrivate: false,
                statusFilter: string.IsNullOrEmpty(status) ? null : Enum.Parse<RoomStatus>(status)
            );

            return Ok(ApiResponse<object>.CreateSuccess(new
            {
                Rooms = roomListResult.Items.Select(room => new
                {
                    RoomId = room.Id,
                    RoomName = room.Name,
                    HostName = room.OwnerName,
                    PlayerCount = room.CurrentPlayers,
                    MaxPlayers = room.MaxPlayers,
                    HasPassword = room.HasPassword,
                    Status = room.Status.ToString(),
                    CreatedAt = room.CreatedAt
                }).ToList(),
                TotalCount = roomListResult.TotalCount,
                CurrentPage = page,
                PageSize = pageSize,
                TotalPages = (int)Math.Ceiling((double)roomListResult.TotalCount / pageSize)
            }, "获取房间列表成功"));
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取房间列表时发生错误");
            return StatusCode(500, ApiResponse<object>.CreateFailure("获取房间列表失败"));
        }
    }

    /// <summary>
    /// 加入房间
    /// POST /api/room/{roomId}/join
    /// </summary>
    [HttpPost("{roomId}/join")]
    public async Task<ActionResult<ApiResponse<object>>> JoinRoomAsync(
        Guid roomId, 
        [FromBody] JoinRoomRequest request)
    {
        try
        {
            var userId = GetCurrentUserId();
            if (userId == Guid.Empty)
            {
                return Unauthorized(ApiResponse<object>.CreateFailure("用户未认证"));
            }

            _logger.LogInformation("用户 {UserId} 尝试加入房间 {RoomId}", userId, roomId);

            var joinResult = await _roomService.JoinRoomAsync(
                roomId: roomId,
                userId: userId,
                password: request.Password
            );

            if (!joinResult.Success)
            {
                return BadRequest(ApiResponse<object>.CreateFailure(
                    string.Join("; ", joinResult.Errors)));
            }

            return Ok(ApiResponse<object>.CreateSuccess(new
            {
                RoomId = roomId,
                Message = "成功加入房间"
            }, "加入房间成功"));
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "加入房间时发生错误: RoomId={RoomId}", roomId);
            return StatusCode(500, ApiResponse<object>.CreateFailure("加入房间失败"));
        }
    }

    /// <summary>
    /// 离开房间
    /// POST /api/room/{roomId}/leave
    /// </summary>
    [HttpPost("{roomId}/leave")]
    public async Task<ActionResult<ApiResponse<object>>> LeaveRoomAsync(Guid roomId)
    {
        try
        {
            var userId = GetCurrentUserId();
            if (userId == Guid.Empty)
            {
                return Unauthorized(ApiResponse<object>.CreateFailure("用户未认证"));
            }

            _logger.LogInformation("用户 {UserId} 离开房间 {RoomId}", userId, roomId);

            var leaveResult = await _roomService.LeaveRoomAsync(roomId, userId);

            if (!leaveResult.Success)
            {
                return BadRequest(ApiResponse<object>.CreateFailure(
                    string.Join("; ", leaveResult.Errors)));
            }

            return Ok(ApiResponse<object>.CreateSuccess(new
            {
                RoomId = roomId,
                UserId = userId,
                RoomDeleted = leaveResult.RoomDeleted,
                NewOwnerId = leaveResult.NewOwnerId,
                Message = leaveResult.Message
            }, "离开房间成功"));
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "离开房间时发生错误: RoomId={RoomId}", roomId);
            return StatusCode(500, ApiResponse<object>.CreateFailure("离开房间失败"));
        }
    }

    /// <summary>
    /// 获取房间详情
    /// GET /api/room/{roomId}
    /// </summary>
    [HttpGet("{roomId}")]
    public async Task<ActionResult<ApiResponse<object>>> GetRoomDetailsAsync(Guid roomId)
    {
        try
        {
            var userId = GetCurrentUserId();
            _logger.LogDebug("获取房间详情: RoomId={RoomId}, UserId={UserId}", roomId, userId);

            var roomDetails = await _roomService.GetRoomDetailAsync(roomId, userId);

            if (roomDetails == null)
            {
                return NotFound(ApiResponse<object>.CreateFailure("房间不存在"));
            }

            return Ok(ApiResponse<object>.CreateSuccess(new
            {
                RoomId = roomDetails.Id,
                RoomName = roomDetails.Name,
                HostId = roomDetails.OwnerId,
                HostName = roomDetails.OwnerName,
                Status = roomDetails.Status.ToString(),
                MapSize = "default", // 暂时硬编码
                GameDuration = 300, // 暂时硬编码
                MaxPlayers = roomDetails.MaxPlayers,
                CurrentPlayers = roomDetails.CurrentPlayers,
                IsPrivate = roomDetails.IsPrivate,
                HasPassword = roomDetails.HasPassword,
                Players = roomDetails.Players.Select(p => new
                {
                    PlayerId = p.UserId,
                    PlayerName = p.UserName,
                    IsReady = p.IsReady,
                    JoinedAt = p.JoinedAt,
                    IsHost = p.UserId == roomDetails.OwnerId
                }).ToList(),
                CreatedAt = roomDetails.CreatedAt
            }, "获取房间详情成功"));
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取房间详情时发生错误: RoomId={RoomId}", roomId);
            return StatusCode(500, ApiResponse<object>.CreateFailure("获取房间详情失败"));
        }
    }

    /// <summary>
    /// 更新房间设置
    /// PUT /api/room/{roomId}/settings
    /// </summary>
    [HttpPut("{roomId}/settings")]
    public async Task<ActionResult<ApiResponse<object>>> UpdateRoomSettingsAsync(
        Guid roomId, 
        [FromBody] UpdateRoomSettingsRequest request)
    {
        try
        {
            var userId = GetCurrentUserId();
            if (userId == Guid.Empty)
            {
                return Unauthorized(ApiResponse<object>.CreateFailure("用户未认证"));
            }

            _logger.LogInformation("用户 {UserId} 更新房间设置 {RoomId}", userId, roomId);

            var updateResult = await _roomService.UpdateRoomAsync(
                roomId: roomId,
                userId: userId,
                name: request.RoomName,
                maxPlayers: request.MaxPlayers,
                password: request.Password,
                isPrivate: request.IsPrivate
            );

            if (!updateResult.Success)
            {
                return BadRequest(ApiResponse<object>.CreateFailure(
                    string.Join("; ", updateResult.Errors)));
            }

            return Ok(ApiResponse<object>.CreateSuccess(new
            {
                RoomId = roomId,
                UpdatedSettings = new
                {
                    request.RoomName,
                    HasPassword = !string.IsNullOrEmpty(request.Password),
                    request.MaxPlayers,
                    request.GameMode,
                    request.MapSize,
                    request.GameDuration,
                    request.IsPrivate
                },
                UpdatedAt = DateTime.UtcNow
            }, "房间设置更新成功"));
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "更新房间设置时发生错误: RoomId={RoomId}", roomId);
            return StatusCode(500, ApiResponse<object>.CreateFailure("更新房间设置失败"));
        }
    }

    /// <summary>
    /// 删除房间
    /// DELETE /api/room/{roomId}
    /// </summary>
    [HttpDelete("{roomId}")]
    public async Task<ActionResult<ApiResponse<object>>> DeleteRoomAsync(Guid roomId)
    {
        try
        {
            var userId = GetCurrentUserId();
            if (userId == Guid.Empty)
            {
                return Unauthorized(ApiResponse<object>.CreateFailure("用户未认证"));
            }

            _logger.LogInformation("用户 {UserId} 删除房间 {RoomId}", userId, roomId);

            var deleteResult = await _roomService.DeleteRoomAsync(roomId, userId);

            if (!deleteResult.Success)
            {
                return BadRequest(ApiResponse<object>.CreateFailure(
                    string.Join("; ", deleteResult.Errors)));
            }

            return Ok(ApiResponse<object>.CreateSuccess(new
            {
                RoomId = roomId,
                DeletedAt = DateTime.UtcNow
            }, "房间删除成功"));
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "删除房间时发生错误: RoomId={RoomId}", roomId);
            return StatusCode(500, ApiResponse<object>.CreateFailure("删除房间失败"));
        }
    }

    /// <summary>
    /// 踢出玩家
    /// POST /api/room/{roomId}/kick/{playerId}
    /// </summary>
    [HttpPost("{roomId}/kick/{playerId}")]
    public async Task<ActionResult<ApiResponse<object>>> KickPlayerAsync(Guid roomId, Guid playerId)
    {
        try
        {
            var userId = GetCurrentUserId();
            if (userId == Guid.Empty)
            {
                return Unauthorized(ApiResponse<object>.CreateFailure("用户未认证"));
            }

            _logger.LogInformation("用户 {UserId} 踢出房间 {RoomId} 中的玩家 {PlayerId}", userId, roomId, playerId);

            var kickResult = await _roomService.KickPlayerAsync(roomId, userId, playerId);

            if (!kickResult.Success)
            {
                return BadRequest(ApiResponse<object>.CreateFailure(
                    string.Join("; ", kickResult.Errors)));
            }

            return Ok(ApiResponse<object>.CreateSuccess(new
            {
                RoomId = roomId,
                KickedPlayerId = playerId,
                KickedAt = DateTime.UtcNow
            }, "玩家已被踢出房间"));
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "踢出玩家时发生错误: RoomId={RoomId}, PlayerId={PlayerId}", roomId, playerId);
            return StatusCode(500, ApiResponse<object>.CreateFailure("踢出玩家失败"));
        }
    }

    /// <summary>
    /// 切换准备状态
    /// POST /api/room/{roomId}/ready
    /// </summary>
    [HttpPost("{roomId}/ready")]
    public async Task<ActionResult<ApiResponse<object>>> ToggleReadyAsync(Guid roomId, [FromBody] ToggleReadyRequest request)
    {
        try
        {
            var userId = GetCurrentUserId();
            if (userId == Guid.Empty)
            {
                return Unauthorized(ApiResponse<object>.CreateFailure("用户未认证"));
            }

            _logger.LogInformation("用户 {UserId} 在房间 {RoomId} 切换准备状态为 {IsReady}", userId, roomId, request.IsReady);

            var readyResult = await _roomService.SetPlayerReadyAsync(roomId, userId, request.IsReady);

            if (!readyResult.Success)
            {
                return BadRequest(ApiResponse<object>.CreateFailure(
                    string.Join("; ", readyResult.Errors)));
            }

            return Ok(ApiResponse<object>.CreateSuccess(new
            {
                RoomId = roomId,
                UserId = userId,
                IsReady = request.IsReady,
                UpdatedAt = DateTime.UtcNow
            }, request.IsReady ? "已准备" : "取消准备"));
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "切换准备状态时发生错误: RoomId={RoomId}", roomId);
            return StatusCode(500, ApiResponse<object>.CreateFailure("切换准备状态失败"));
        }
    }

    /// <summary>
    /// 获取房间内玩家列表
    /// GET /api/room/{roomId}/players
    /// </summary>
    [HttpGet("{roomId}/players")]
    public async Task<ActionResult<ApiResponse<object>>> GetRoomPlayersAsync(Guid roomId)
    {
        try
        {
            var userId = GetCurrentUserId();
            if (userId == Guid.Empty)
            {
                return Unauthorized(ApiResponse<object>.CreateFailure("用户未认证"));
            }

            _logger.LogDebug("获取房间玩家列表: RoomId={RoomId}", roomId);

            var roomDetails = await _roomService.GetRoomDetailAsync(roomId, userId);

            if (roomDetails == null)
            {
                return NotFound(ApiResponse<object>.CreateFailure("房间不存在"));
            }

            return Ok(ApiResponse<object>.CreateSuccess(new
            {
                RoomId = roomId,
                PlayerCount = roomDetails.CurrentPlayers,
                MaxPlayers = roomDetails.MaxPlayers,
                Players = roomDetails.Players.Select(p => new
                {
                    PlayerId = p.UserId,
                    PlayerName = p.UserName,
                    IsReady = p.IsReady,
                    IsHost = p.UserId == roomDetails.OwnerId,
                    JoinedAt = p.JoinedAt
                }).ToList()
            }, "获取房间玩家列表成功"));
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取房间玩家列表时发生错误: RoomId={RoomId}", roomId);
            return StatusCode(500, ApiResponse<object>.CreateFailure("获取房间玩家列表失败"));
        }
    }

    /// <summary>
    /// 发送房间聊天消息
    /// POST /api/room/{roomId}/chat/send
    /// </summary>
    [HttpPost("{roomId}/chat/send")]
    public async Task<ActionResult<ApiResponse<object>>> SendChatMessage(Guid roomId, SendChatMessageRequest request)
    {
        try
        {
            var userId = GetCurrentUserId();
            if (userId == Guid.Empty)
            {
                return Unauthorized(ApiResponse<object>.CreateFailure("用户未认证"));
            }

            _logger.LogDebug("发送聊天消息: RoomId={RoomId}, UserId={UserId}", roomId, userId);

            // 验证请求
            if (string.IsNullOrWhiteSpace(request.Message))
            {
                return BadRequest(ApiResponse<object>.CreateFailure("消息内容不能为空"));
            }

            if (request.Message.Length > 500)
            {
                return BadRequest(ApiResponse<object>.CreateFailure("消息内容过长，最多500字符"));
            }

            // 调用服务发送消息
            var result = await _roomService.SendChatMessageAsync(roomId, userId, request.Message, request.MessageType ?? "text");

            if (!result.Success)
            {
                return BadRequest(ApiResponse<object>.CreateFailure(
                    result.Message,
                    result.Errors
                ));
            }

            // 实时广播聊天消息给房间内所有用户
            var roomGroupName = $"room_chat_{roomId}";
            await _hubContext.Clients.Group(roomGroupName).SendAsync("NewChatMessage", new
            {
                Id = result.MessageInfo!.Id,
                RoomId = result.MessageInfo.RoomId,
                UserId = result.MessageInfo.UserId,
                Username = result.MessageInfo.Username,
                Message = result.MessageInfo.Message,
                MessageType = result.MessageInfo.MessageType,
                CreatedAt = result.MessageInfo.CreatedAt,
                IsRealtime = true,
                Source = "api", // 标识消息来源
                Timestamp = DateTime.UtcNow
            });

            return Ok(ApiResponse<object>.CreateSuccess(result.MessageInfo, result.Message));
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "发送聊天消息时发生错误: RoomId={RoomId}", roomId);
            return StatusCode(500, ApiResponse<object>.CreateFailure("发送聊天消息失败"));
        }
    }

    /// <summary>
    /// 获取房间聊天历史
    /// GET /api/room/{roomId}/chat/history
    /// </summary>
    [HttpGet("{roomId}/chat/history")]
    public async Task<ActionResult<ApiResponse<object>>> GetChatHistory(Guid roomId, [FromQuery] int limit = 50, [FromQuery] int offset = 0)
    {
        try
        {
            var userId = GetCurrentUserId();
            if (userId == Guid.Empty)
            {
                return Unauthorized(ApiResponse<object>.CreateFailure("用户未认证"));
            }

            _logger.LogDebug("获取聊天历史: RoomId={RoomId}, Limit={Limit}, Offset={Offset}", roomId, limit, offset);

            // 验证参数
            if (limit <= 0 || limit > 100)
            {
                return BadRequest(ApiResponse<object>.CreateFailure("limit 参数必须在 1-100 之间"));
            }

            if (offset < 0)
            {
                return BadRequest(ApiResponse<object>.CreateFailure("offset 参数不能小于 0"));
            }

            // 调用服务获取聊天历史
            var result = await _roomService.GetChatHistoryAsync(roomId, userId, limit, offset);

            if (!result.Success)
            {
                return BadRequest(ApiResponse<object>.CreateFailure(
                    result.Message,
                    result.Errors
                ));
            }

            return Ok(ApiResponse<object>.CreateSuccess(new
            {
                RoomId = roomId,
                Messages = result.Messages,
                Total = result.Total,
                Limit = result.Limit,
                Offset = result.Offset
            }, result.Message));
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取聊天历史时发生错误: RoomId={RoomId}", roomId);
            return StatusCode(500, ApiResponse<object>.CreateFailure("获取聊天历史失败"));
        }
    }

    /// <summary>
    /// 开始游戏（房主专用）
    /// POST /api/room/{roomId}/start-game
    /// </summary>
    [HttpPost("{roomId}/start-game")]
    public async Task<ActionResult<ApiResponse<object>>> StartGameAsync(Guid roomId)
    {
        try
        {
            var userId = GetCurrentUserId();
            if (userId == Guid.Empty)
            {
                return Unauthorized(ApiResponse<object>.CreateFailure("用户未认证"));
            }
            
            var username = GetCurrentUsername();
            _logger.LogInformation("[调试] 开始游戏请求 - UserId: {UserId}, Username: {Username}, RoomId: {RoomId}", userId, username, roomId);

            _logger.LogInformation("用户 {UserId}({Username}) 尝试开始房间 {RoomId} 的游戏", userId, username, roomId);

            // 调用应用层服务开始游戏，传入用户名
            var result = await _roomService.StartGameAsync(roomId, userId, username);

            if (!result.Success)
            {
                return BadRequest(ApiResponse<object>.CreateFailure(
                    result.Message,
                    result.Errors
                ));
            }

            _logger.LogInformation("房间 {RoomId} 的游戏已开始，游戏ID: {GameId}", roomId, result.GameId);
            
            // 向房间聊天组广播游戏开始事件，便于所有客户端（包括非房主）自动跳转
            var roomGroupName = $"room_chat_{roomId}";
            _logger.LogInformation("[调试] 准备向房间组广播GameStarted事件 - GroupName: {GroupName}, GameId: {GameId}", roomGroupName, result.GameId);
            
            await _hubContext.Clients.Group(roomGroupName).SendAsync("GameStarted", new
            {
                GameId = result.GameId,
                RoomId = roomId,
                Message = "游戏已开始",
                Timestamp = DateTime.UtcNow
            });
            _logger.LogInformation("[调试] GameStarted事件已广播到房间组 - GroupName: {GroupName}", roomGroupName);

            // 同时广播房间状态变化，作为前端兜底监听（例如连接晚到或丢包场景）
            _logger.LogInformation("[调试] 准备向房间组广播RoomStatusChanged事件 - GroupName: {GroupName}, Status: Playing", roomGroupName);
            await _hubContext.Clients.Group(roomGroupName).SendAsync("RoomStatusChanged", new
            {
                RoomId = roomId,
                Status = "Playing",
                GameId = result.GameId,
                Timestamp = DateTime.UtcNow
            });
            _logger.LogInformation("[调试] RoomStatusChanged事件已广播到房间组 - GroupName: {GroupName}", roomGroupName);

            return Ok(ApiResponse<object>.CreateSuccess(new
            {
                GameId = result.GameId,
                RoomId = roomId
            }, result.Message));
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "开始游戏时发生错误: RoomId={RoomId}", roomId);
            return StatusCode(500, ApiResponse<object>.CreateFailure("开始游戏失败"));
        }
    }

    /// <summary>
    /// 获取当前用户ID
    /// </summary>
    private Guid GetCurrentUserId()
    {
        var userIdClaim = User.FindFirst(ClaimTypes.NameIdentifier);
        return userIdClaim != null && Guid.TryParse(userIdClaim.Value, out var userId) 
            ? userId : Guid.Empty;
    }

    /// <summary>
    /// 获取当前用户名
    /// </summary>
    private string GetCurrentUsername()
    {
        var usernameClaim = User.FindFirst(ClaimTypes.Name) ?? User.FindFirst("unique_name");
        return usernameClaim?.Value ?? "Unknown";
    }
}
